﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using Sukul.SharePoint.Common;
using Sukul.SharePoint.Common.DTO;
using Sukul.SharePoint.Taxomatic;
using DTO = Sukul.SharePoint.Taxomatic.DTO;
using Sukul.SharePoint.Taxomatic.Service;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Taxonomy;
using System.Collections.ObjectModel;

namespace Taxomatic.Console
{
    class Program
    {
        static string outputPath = @"c:\Taxomatic.xml";
        static string url = string.Empty;
        static string mode = string.Empty;
        static string input = string.Empty;
        static ConsoleKeyInfo key = new ConsoleKeyInfo();

        static void Main(string[] args)
        {
            try
            {
                Header();
                if (args.Length == 0 && string.IsNullOrEmpty(args.FirstOrDefault(a => a.ToLower().Contains("url:"))))
                {
                    Usage();
                }
                else
                {
                    mode = args.First(a => a.ToLower().Contains("mode:")).ToLower().Replace("mode:", string.Empty);
                    url = args.First(a => a.ToLower().Contains( "url:")).ToLower().Replace("url:", string.Empty);
                    switch (mode.ToLower())
                    {
                        case "import":
                            if (args.FirstOrDefault(a => a.ToLower().Contains("input")) != null)
                            {
                                input  = args.First(a => a.ToLower().Contains("input")).ToLower().Replace("input:", string.Empty);
                            } else {
                                throw new ApplicationException("Input file missing");
                            }
                            System.Console.WriteLine("Do you want to import terms for site: {0}", url);
                            System.Console.WriteLine("If this looks OK, press Y to continue");
                            key = System.Console.ReadKey();
                            if (key.Key == ConsoleKey.Y)
                            {
                                System.Console.WriteLine("");
                                Import(url, input);
                            }
                            else
                            {
                                System.Console.WriteLine("Aborted!");
                            }
                            break;
                        case "sync":
                            System.Console.WriteLine("Do you want to sync the hidden list for site: {0}", url);
                            System.Console.WriteLine("If this looks OK, press Y to continue");
                            key = System.Console.ReadKey();
                            if (key.Key == ConsoleKey.Y)
                            {
                                System.Console.WriteLine("");
                                SyncHiddenList(url);
                            }
                            else
                            {
                                System.Console.WriteLine("Aborted!");
                            }
                            break;
                        case "export":
                            if (args.FirstOrDefault(a => a.ToLower().Contains("output")) != null)
                            {
                                outputPath = args.First(a => a.ToLower().Contains("output")).ToLower().Replace("output:", string.Empty);
                            }
                            System.Console.WriteLine("Url = {0}", url);
                            System.Console.WriteLine("Output Path = {0}", outputPath);
                            System.Console.WriteLine("If this looks OK, press Y to continue");
                            key = System.Console.ReadKey();
                            if (key.Key == ConsoleKey.Y)
                            {

                                System.Console.WriteLine("");
                                System.Console.WriteLine("Exporting taxonomy ....");
                                DTO.TermStores tree = GetTermTree();
                                string xml = ServiceBase.Instance.XMLSerialize(tree);
                                File.WriteAllText(outputPath, xml);
                                System.Console.WriteLine("Taxonomy written to " + outputPath);
                            }
                            else
                            {
                                System.Console.WriteLine("Aborted!");
                            }
                            break;
                    }
                }
            }
            catch (Exception ex)
            {
                System.Console.WriteLine(ex.ToString());
            }
            System.Console.WriteLine("Press ENTER to exit");
            System.Console.ReadLine();
        }

        static void Header()
        {
            System.Console.Clear();
            System.Console.WriteLine("----------------- Taxomatic, Console Edition--------------");
            System.Console.WriteLine("This program can be used to either export the SharePoint taxonomy tree to an XML file or to sync the hidden Taxonomy list in a site");
            System.Console.WriteLine("");
            System.Console.WriteLine("-------- Written by Shailen Sukul (http://shailen.sukul.org) ---------");
            System.Console.WriteLine("******** Hosted at Codeplex (http://taxomatic.codeplex.com)***********");
            System.Console.WriteLine("");
        }

        static void Usage()
        {
            System.Console.WriteLine("Usage:");
            System.Console.WriteLine("Taxomatic.Console.exe <args>");
            System.Console.WriteLine("Where Args = ");
            System.Console.WriteLine("mode:sync|export");
            System.Console.WriteLine("");
            System.Console.WriteLine("Arguments for mode:sync");
            System.Console.WriteLine("url:<<site url>>");
            System.Console.WriteLine("Example: Taxomatic.Console.exe mode:sync url:http://mysite.com");
            System.Console.WriteLine("");
            System.Console.WriteLine("Arguments for mode:export");
            System.Console.WriteLine("url:<<site url>>");
            System.Console.WriteLine("output:<<file to write taxonomy to>>. By default it will be written to " + outputPath);
            System.Console.WriteLine(@"Example: Taxomatic.Console.exe mode:export url://http://mysite.com output:c:\taxomatic.xml");
            System.Console.WriteLine("");
        }

        public static void Import(string siteUrl, string inputfile)
        {
            List<string> error = new List<string>();
            List<string> log = new List<string>();
            new Sukul.SharePoint.Taxomatic.Service.TaxonomyHelper().ImportTaxonomy2(inputfile, ref log, ref error, siteUrl);
            foreach (string e in error)
            {
                System.Console.WriteLine(e);
            }
        }

        public static bool SyncHiddenList(string siteUrl)
        {
            bool ok = false;
            System.Console.WriteLine("Syncing taxonomy for hidden list at site: " + siteUrl);

            using (SPSite site = new SPSite(siteUrl))
            {
                TaxonomySession.SyncHiddenList(site);
                System.Console.WriteLine("Sucessfull synced taxonomy for hidden list at site: " + siteUrl);
                ok = true;
            }

            return ok;
        }
        public static DTO.TermStores GetTermTree()
        {
            DTO.TermStores termStores = new DTO.TermStores();
            DTO.TermStore termStore = null;
            DTO.TaxonomyGroup termGroup = null;
            DTO.Termset termSet = null;

            using (SPSite mySite = new SPSite(url))
            {
                TaxonomySession session = new TaxonomySession(mySite);

                // Get all the TermStores associated with the provided site.
                TermStoreCollection stores = session.TermStores;
                //TermStore store = session.DefaultSiteCollectionTermStore;

                foreach (var store in stores)
                {
                    if (store.Name.Equals("System")) { continue; }
                    termStore = new DTO.TermStore();
                    termStore.Id = store.Id;
                    termStore.Name = store.Name;
                    termStore.WorkingLanguage = store.WorkingLanguage;
                    foreach (var language in store.Languages)
                    {
                        termStore.Languages.Add(language);
                    }

                    foreach (var group in store.Groups)
                    {
                        termGroup = new DTO.TaxonomyGroup();
                        termGroup.Id = group.Id;
                        termGroup.Name = group.Name;
                        termGroup.CreatedDate = group.CreatedDate;
                        termGroup.Description = group.Description;

                        foreach (var termset in group.TermSets)
                        {
                            termSet = new DTO.Termset();
                            termSet.Id = termset.Id;
                            termSet.Name = termset.Name;
                            termSet.Description = termset.Description;
                            termSet.CreatedDate = termset.CreatedDate;
                            termSet.IsAvailableForTagging = termset.IsAvailableForTagging;
                            termSet.IsOpenForTermCreation = termset.IsOpenForTermCreation;
                            termSet.LastModifiedDate = termset.LastModifiedDate;

                            foreach (Term topTerm in termset.Terms)
                            {
                                termSet.Terms = TraverseTermSet(termset.Terms);
                            }
                            termGroup.Termsets.Add(termSet);
                        }
                        termStore.TaxonomyGroups.Add(termGroup);
                    }
                    termStores.Add(termStore);
                }
            }
            return termStores;
        }

        private static Collection<DTO.Term> TraverseTermSet(TermCollection tc)
        {
            Collection<DTO.Term> terms = new Collection<DTO.Term>();
            DTO.Label lbl = null;

            DTO.Term term = null;
            foreach (Term t in tc)
            {
                term = new DTO.Term();
                term.Id = t.Id;
                term.Name = t.Name;
                term.IsAvailableForTagging = t.IsAvailableForTagging;
                term.IsDeprecated = t.IsDeprecated;
                term.IsKeyword = t.IsKeyword;
                term.IsReused = t.IsReused;
                term.IsRoot = t.IsRoot;
                term.IsSourceTerm = t.IsSourceTerm;
                foreach (var label in t.Labels)
                {
                    lbl = new DTO.Label();
                    lbl.Language = label.Language;
                    lbl.Value = label.Value;
                    lbl.IsDefaultForLanguage = label.IsDefaultForLanguage;
                    term.Labels.Add(lbl);
                }

                terms.Add(term);

                if (null != t.Terms)
                {
                    term.Terms = TraverseTermSet(t.Terms);
                }
            }
            return terms;
        }
    }
}
